package usecasesimpl;

import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import usecases.GestionPartie;
import dao.JoueurDao;
import dao.PartieDao;
import dao.TourDao;
import domaine.Action;
import domaine.De;
import domaine.Joueur;
import domaine.Partie;
import domaine.Partie.Etat;
import domaine.Tour;
import enumere.Couleur;

//@Singleton
//@Startup
@Stateless
public class GestionPartieImpl implements GestionPartie {

	@EJB
	PartieDao partieDao;
	@EJB
	JoueurDao joueurDao;
	@EJB
	TourDao tourDao;

	@Override
	public Partie creerUnePartie(Joueur joueur, String nomPartie) {
		Partie p = new Partie(joueur, nomPartie);
		p = partieDao.enregistrer(p);
		return p;
	}

	@Override
	public Partie rejoindreUnePartie(int idPartie, Joueur joueur) {
		Partie p = partieDao.rechercher(idPartie);
		if (!p.ajouterJoueur(joueur)) {
			return null;
		}
		p = partieDao.mettreAJour(p);
		p = chargerPartie(p);
		return p;
	}

	public List<Partie> listerPartiesTerminees() {
		return partieDao.listerPartieTerminee();
	}

	@Override
	public List<Partie> listerPartiesEnAttente() {
		List<Partie> listeParties = partieDao.listerPartieEnAttente();
		for (Partie partie : listeParties) {
			partie = chargerPartie(partie);
		}
		return listeParties;
	}

	@Override
	public List<Partie> listerParties() {
		List<Partie> listeParties = partieDao.lister();
		for (Partie partie : listeParties) {
			partie = chargerPartie(partie);
		}
		return listeParties;
	}

	// renvoie le premier tour de la partie
	@Override
	public Tour jouerUnePartie(Partie partie) {
		partie = chargerPartie(partie);
		Tour t = partie.jouerUnTour(partie);
		return t;
	}

	@Override
	public String visualiserJournalPartie(int partie) {
		String aRet = "";
		Partie p = partieDao.rechercher(partie);
		if (p != null) {

			p = chargerPartie(p);
			aRet += "Nom de la partie : " + p.getNom() + "<br>";
			aRet += "Etat de la partie = " + p.getEtat() + "<br>";
			Calendar debut = p.getDebut();
			Calendar fin = p.getDebut();
			if (debut == null) {
				aRet += "Debut de la partie : La partie n'a pas débuté<br>";
			} else {
				aRet += "Debut de la partie : "
						+ debut.get(Calendar.DAY_OF_MONTH) + "/"
						+ debut.get(Calendar.MONTH) + "/"
						+ debut.get(Calendar.YEAR) + " à "
						+ debut.get(Calendar.HOUR_OF_DAY) + "h"
						+ debut.get(Calendar.MINUTE) + "<br>";
				if (p.terminee()) {
					aRet += "Fin de la partie : "
							+ fin.get(Calendar.DAY_OF_MONTH) + "/"
							+ fin.get(Calendar.MONTH) + "/"
							+ fin.get(Calendar.YEAR) + " à "
							+ fin.get(Calendar.HOUR_OF_DAY) + "h"
							+ fin.get(Calendar.MINUTE) + "<br>";
				} else {
					aRet += "La partie est toujours en cours<br>";
				}
			}
			aRet += "Adversaires : ";
			if (p.getNbJoueurs() == 0) {
				aRet += "Aucun joueur";
			} else {
				Iterator<Joueur> it = p.joueurs();
				while (it.hasNext()) {
					aRet += it.next().getPseudo() + ", ";
				}
				aRet = aRet.substring(0, aRet.length() - 1);
				aRet += "<br>";
			}

			// si la partie est en attente, on ne s'occupe pas des tours
			if (p.getEtat().equals(Etat.EN_ATTENTE)) {
				return aRet;
			}
			Iterator<Tour> itTour = p.getTours().iterator();
			while (itTour.hasNext()) {
				Tour t = itTour.next();
				t = tourDao.chargerTout(t);
				aRet += "Les des lances sont : le de Ordre indique \""
						+ t.getDeOrdre() + "\"<br>";

				Iterator<De> itDe = t.getDes().iterator();
				int[] deRouges = new int[3];
				int[] deNoirs = new int[3];
				int[] deBlancs = new int[3];
				while (itDe.hasNext()) {
					De de = itDe.next();
					if (de.getCouleur().equals(Couleur.ROUGE))
						deRouges[deRouges.length - 1] = de.getValeur();
					else if (de.getCouleur().equals(Couleur.NOIR))
						deNoirs[deNoirs.length - 1] = de.getValeur();
					else if (de.getCouleur().equals(Couleur.BLANC))
						deBlancs[deBlancs.length - 1] = de.getValeur();
				}

				aRet += "Les des rouges sont : ";
				aRet += deRouges[0] + ", ";
				aRet += deRouges[1] + ", ";
				aRet += deRouges[2] + "<br>";

				aRet += "Les des noirs sont : ";
				aRet += deNoirs[0] + ", ";
				aRet += deNoirs[1] + ", ";
				aRet += deNoirs[2] + "<br>";

				aRet += "Les des blancs sont : ";
				aRet += deBlancs[0] + ", ";
				aRet += deBlancs[1] + ", ";
				aRet += deBlancs[2] + "<br>";

				Map<Joueur, Action> joueursActions = t.getJoueursAction();
				Collection<Joueur> joueurs = joueursActions.keySet();
				for (Joueur joueur : joueurs) {
					if(joueursActions.get(joueur).getLinkChoisis()!=null){
						aRet += joueur.getPseudo() + " prend un link "
								+ joueursActions.get(joueur).getLinkChoisis()
								+ "<br>";
					}else{
						aRet += joueur.getPseudo() + " n'a pas choisi de link. <br>";
					}
					aRet += "Point de vie restant : "
							+ joueursActions.get(joueur).getGemmeRestantes()
							+ "<br>";
				}
				aRet += "<br><br>";
			}

			if (p.getEtat() == Etat.TERMINEE) {
				Joueur gagnant = null;
				Iterator<Joueur> itGagnant = p.getJoueurs().iterator();
				while (itGagnant.hasNext()) {
					Joueur j = itGagnant.next();
					if (p.points(j) > 0) {
						gagnant = j;
						break;
					}
				}
				if (gagnant == null)
					aRet += "Il n'y a pas de gagnant.<br>";
				else {
					/* int nbPerdant = 0; */
					// aRet += gagnant.getPseudo() + " a gagné car ";
					aRet += gagnant.getPseudo() + " a gagné. <br>";
					/*
					 * Iterator<Joueur> itPerdant = p.getJoueurs().iterator();
					 * while (itPerdant.hasNext()) { Joueur j =
					 * itPerdant.next(); if (j.getId() != gagnant.getId()) {
					 * aRet += j.getPseudo() + " ,"; nbPerdant++; } }
					 * aRet.substring(aRet.length() - 1); if (nbPerdant > 1)
					 * aRet += " n'ont plus de vies.<br>"; else aRet +=
					 * " n'a plus de vies.<br>";
					 */
				}

				long durée = p.getFin().getTimeInMillis()
						- p.getDebut().getTimeInMillis();
				Calendar c = new GregorianCalendar();
				c.setTimeInMillis(durée);
				aRet += "La partie est terminé. Cela a pris "
						+ c.get(Calendar.MINUTE) + "h "
						+ c.get(Calendar.MINUTE) + "mn "
						+ c.get(Calendar.SECOND) + "sec <br>";
			}
		} else {
			aRet = "La partie a été annulée. Cliquez sur le lien ci-dessous pour revenir à la page précédente.<br>";
		}
		return aRet;
	}

	@Override
	public boolean quitterLaPartie(Joueur joueur, Partie partie) {
		// si la partie est terminée, il ne faut pas supprimé le joueur de la
		// partie car il a ses gemmes enregistrés
		if (partie.terminee()) {
			// return true car le joueur peut quitter la partie
			return true;
		} else {
			partie = partieDao.chargerTout(partie);
			boolean desinscrit = partie.desinscrire(joueur);
			if (desinscrit) {
				partie = partieDao.mettreAJour(partie);
			}
			// si la partie est annulé ou en attente, on supprime la partie
			if (partie.annulee()
					|| (partie.enAttente() && partie.getNbJoueurs() == 0)) {
				partieDao.supprimer(partie.getId());
			}
			return desinscrit;
		}
	}

	@Override
	public List<Joueur> listerJoueurs(Partie partie) {
		return joueurDao.listerJoueurs(partie.getId());
	}

	@Override
	public boolean commencerPartie(Partie partie) {
		partie = chargerPartie(partie);
		if (partie.getNbJoueurs() < 2)
			return false;
		boolean commencee = partie.commencerPartie();
		if (commencee) {
			partie = partieDao.mettreAJour(partie);
		}
		return commencee;
	}

	@Override
	public boolean estFinie(Partie partie) {
		if (partie.getEtat().equals(Etat.TERMINEE)
				|| partie.getEtat().equals(Etat.ANNULEE))
			return false;
		return true;
	}

	@Override
	public boolean annulerPartie(Partie partie) {
		partie = chargerPartie(partie);
		partieDao.supprimer(partie.getId()); // on supprime de la db la partie
												// annulé
		return true;
	}

	@Override
	public Partie chargerPartie(Partie partie) {
		if (partie == null) {
			return null;
		}
		if (partie.getId() == 0)
			return partie;
		return partieDao.chargerTout(partie);
	}

	@Override
	public Partie rechercherPartie(int id) {
		Partie p = partieDao.rechercher(id);
		return chargerPartie(p);
	}

	@Override
	public void clear() {
		partieDao.clear();

	}

	@Override
	public Partie terminerPartie(Partie p) {
		p = chargerPartie(p);
		p.terminerPartie();
		p = partieDao.mettreAJour(p);
		return p;
	}
}
